#include "Modelo.h"
#include "../Vista/Vista.h"

using namespace std;

void Modelo::ActualizarVistas()
{
    vector<Vista*>::iterator t;

    for(t = vistas.begin(); t != vistas.end(); t++)
        (*t)->Actualizar();
}

/*
Modelo&
Modelo::operator=(const &Modelo m)
{
    if (this != &m) {
        vistas.erase(vistas.begin(), vistas.end());
        vistas = m.vistas;
    }
 *
 * return *this;
}
 * */

void Modelo::guardarAFichero(vector<Primitiva*> v, string f)
{
    ofstream file(f.c_str());

    if(file.is_open()) {
        for(int i = 0; i < (signed) v.size(); i++) {
            Punto* p_subclass = dynamic_cast<Punto*>(v[i]);
            Linea* l_subclass = dynamic_cast<Linea*>(v[i]);
            Rectangulo* r_subclass = dynamic_cast<Rectangulo*>(v[i]);
            Triangulo* t_subclass = dynamic_cast<Triangulo*>(v[i]);
            Circulo* c_subclass = dynamic_cast<Circulo*>(v[i]);
            Conjunto* cj_subclass = dynamic_cast<Conjunto*>(v[i]);
            Imagen* img_subclass = dynamic_cast<Imagen*>(v[i]);

            if(p_subclass)
                file << "PUNTO " << p_subclass->GetX() << " " << p_subclass->GetY() << " " <<
                        p_subclass->GetRed() * 255 << " " << p_subclass->GetGreen() * 255 << " " << p_subclass->GetBlue() * 255 << endl;
            else if(l_subclass)
                file << "LINEA " << l_subclass->GetX() << " " << l_subclass->GetY() << " " <<
                        l_subclass->GetRed() * 255 << " " << l_subclass->GetGreen() * 255 << " " << l_subclass->GetBlue() * 255 << " " <<
                        l_subclass->GetQ().GetX() << " " << l_subclass->GetQ().GetY() << endl;
            else if(r_subclass)
                file << "RECTANGULO " << r_subclass->GetX() << " " << r_subclass->GetY() << " " <<
                        r_subclass->GetRed() * 255 << " " << r_subclass->GetGreen() * 255 << " " << r_subclass->GetBlue() * 255 << " " <<
                        r_subclass->GetAncho() << " " << r_subclass->GetAlto() << endl;
            else if(t_subclass)
                file << "TRIANGULO " << t_subclass->GetX() << " " << t_subclass->GetY() << " " <<
                        t_subclass->GetRed() * 255 << " " << t_subclass->GetGreen() * 255 << " " << t_subclass->GetBlue() * 255 << " " <<
                        t_subclass->GetP(1).GetX() << " " << t_subclass->GetP(1).GetY() << " " <<
                        t_subclass->GetP(2).GetX() << " " << t_subclass->GetP(2).GetY() << endl;
            else if(c_subclass)
                file << "CIRCULO " << c_subclass->GetX() << " " << c_subclass->GetY() << " " <<
                        c_subclass->GetRed() * 255 << " " << c_subclass->GetGreen() * 255 << " " << c_subclass->GetBlue() * 255 << " " <<
                        c_subclass->GetRadio() << endl;
            else if(cj_subclass) {
                file << "GRUPO " << cj_subclass->GetX() << " " << cj_subclass->GetY() << endl;
                file << guardarAFichero(cj_subclass->GetComponentes(), true);
                file << "FIN_GRUPO " << endl;
            } else if(img_subclass) {
                file << "IMAGEN " << img_subclass->GetX() << " " << img_subclass->GetY() << " " << img_subclass->GetFileName() << endl;
            }
        }
    }

    file.close();
}

string Modelo::guardarAFichero(vector<Primitiva*> v, bool conj) {
    stringstream file;

    for(int i = 0; i < (signed) v.size(); i++) {
        Punto* p_subclass = dynamic_cast<Punto*>(v[i]);
        Linea* l_subclass = dynamic_cast<Linea*>(v[i]);
        Rectangulo* r_subclass = dynamic_cast<Rectangulo*>(v[i]);
        Triangulo* t_subclass = dynamic_cast<Triangulo*>(v[i]);
        Circulo* c_subclass = dynamic_cast<Circulo*>(v[i]);
        Conjunto* cj_subclass = dynamic_cast<Conjunto*>(v[i]);
        Imagen* img_subclass = dynamic_cast<Imagen*>(v[i]);

        if(p_subclass)
            file << "PUNTO " << p_subclass->GetX() << " " << p_subclass->GetY() << " " <<
                    p_subclass->GetRed() * 255 << " " << p_subclass->GetGreen() * 255 << " " << p_subclass->GetBlue() * 255 << endl;
        else if(l_subclass)
            file << "LINEA " << l_subclass->GetX() << " " << l_subclass->GetY() << " " <<
                    l_subclass->GetRed() * 255 << " " << l_subclass->GetGreen() * 255 << " " << l_subclass->GetBlue() * 255 << " " <<
                    l_subclass->GetQ().GetX() << " " << l_subclass->GetQ().GetY() << endl;
        else if(r_subclass)
            file << "RECTANGULO " << r_subclass->GetX() << " " << r_subclass->GetY() << " " <<
                    r_subclass->GetRed() * 255 << " " << r_subclass->GetGreen() * 255 << " " << r_subclass->GetBlue() * 255 << " " <<
                    r_subclass->GetAncho() << " " << r_subclass->GetAlto() << endl;
        else if(t_subclass)
            file << "TRIANGULO " << t_subclass->GetX() << " " << t_subclass->GetY() << " " <<
                    t_subclass->GetRed() * 255 << " " << t_subclass->GetGreen() * 255 << " " << t_subclass->GetBlue() * 255 << " " <<
                    t_subclass->GetP(1).GetX() << " " << t_subclass->GetP(1).GetY() << " " <<
                    t_subclass->GetP(2).GetX() << " " << t_subclass->GetP(2).GetY() << endl;
        else if(c_subclass)
            file << "CIRCULO " << c_subclass->GetX() << " " << c_subclass->GetY() << " " <<
                    c_subclass->GetRed() * 255 << " " << c_subclass->GetGreen() * 255 << " " << c_subclass->GetBlue() * 255 << " " <<
                    c_subclass->GetRadio() << endl;
        else if(cj_subclass) {
            file << "GRUPO " << cj_subclass->GetX() << " " << cj_subclass->GetY() << " " <<
                    cj_subclass->GetWidth() << " " << cj_subclass->GetHeight() << endl;
            guardarAFichero(cj_subclass->GetComponentes(), true);
            file << "FIN_GRUPO " << endl;
        } else if(img_subclass) {
            file << "IMAGEN " << img_subclass->GetX() << " " << img_subclass->GetY() << " " << img_subclass->GetFileName() << endl;
        }
    }

    return file.str();
}

void Modelo::cargarFichero(string file_name) {
    ifstream file(file_name.c_str());

    if(file.is_open()) {
        vaciarFiguras();
        
        Conjunto* pConjunto = NULL;
        while(!file.eof()) {
            char linea[128];
            file.getline(linea, 128);
            int valores[9], num_values = 0;
            string img_file_name = "";

            for(int i = 0; i < 6; i++)
                valores[i] = 0;

            for(int i = 0; i < (signed)strlen(linea); i++) {
                if(linea[i] == ' ') {
                    valores[num_values] = i + 1;
                    valores[num_values] = atoi(&linea[valores[num_values]]);
                    num_values++;
                }
            }

            //Imprimimos en consola el contenido del fichero
            //cout << "Línea leída: " << linea << " RGB " << valores[2] << valores[3] << valores[4] << endl;

            Punto *p = new Punto(valores[0], valores[1]);

            if(linea[0] == 'P') {
                p->SetColor(valores[2]/255.0, valores[3]/255.0, valores[4]/255.0);
                if(pConjunto)
                    pConjunto->Agrupar(p);
                else
                    figuras.push_back(p);
            } else if(linea[0] == 'L') {
                Punto *p2 = new Punto(valores[5], valores[6]);
                Linea *l = new Linea(*p, *p2);
                l->SetColor(valores[2]/255.0, valores[3]/255.0, valores[4]/255.0);
                if(pConjunto)
                    pConjunto->Agrupar(l);
                else
                    figuras.push_back(l);
            } else if(linea[0] == 'R') {
                Rectangulo *r = new Rectangulo(*p, valores[5], valores[6]);
                r->SetColor(valores[2]/255.0, valores[3]/255.0, valores[4]/255.0);
                if(pConjunto)
                    pConjunto->Agrupar(r);
                else
                    figuras.push_back(r);
            } else if(linea[0] == 'T') {
                Punto *p2 = new Punto(valores[5], valores[6]), *p3 = new Punto(valores[7], valores[8]);
                Triangulo *t = new Triangulo(*p, *p2, *p3);
                t->SetColor(valores[2]/255.0, valores[3]/255.0, valores[4]/255.0);
                if(pConjunto)
                    pConjunto->Agrupar(t);
                else
                    figuras.push_back(t);
            } else if(linea[0] == 'C') {
                Circulo *c = new Circulo(valores[0], valores[4], valores[5]);
                c->SetColor(valores[2]/255.0, valores[3]/255.0, valores[4]/255.0);
                if(pConjunto)
                    pConjunto->Agrupar(c);
                else
                    figuras.push_back(c);
            } else if(linea[0] == 'G') {
                pConjunto = new Conjunto(p->GetX(), p->GetY(), valores[2], valores[3]);
                figuras.push_back(pConjunto);
            } else if(linea[0] == 'F') {
                pConjunto = NULL;
            }  else if(linea[0] == 'I') {
                int aux = 0;
                for(int i = 0; i < (signed)strlen(linea); i++) {
                    if(linea[i] == ' ') {
                        aux++;
                        if(aux == 3)
                            img_file_name = &linea[i + 1];
                    }
                }
                Imagen *img = new Imagen(p->GetX(), p->GetY(), img_file_name);
                cout << "FICHERO_GUARDADO:" << img->GetFileName() << endl;
                if(pConjunto)
                    pConjunto->Agrupar(img);
                else
                    figuras.push_back(img);
            }
        }
    }

    file.close();
}

void Modelo::vaciarFiguras() {
    //Vaciamos los vectores de figuras
    for(int i = 0; i < (signed)figuras.size(); i++) {
        delete figuras[i];
        figuras[i] = NULL;
    }
    for(int i = 0; i < (signed)figurasSeleccionadas.size(); i++) {
        delete figurasSeleccionadas[i];
        figurasSeleccionadas[i] = NULL;
    }
    for(int i = 0; i < (signed)portapapeles.size(); i++) {
        delete portapapeles[i];
        portapapeles[i] = NULL;
    }
    figuras.clear();
    figurasSeleccionadas.clear();
    portapapeles.clear();
}